import { dropHandlers, type SmoothDnD,smoothDnD } from "smooth-dnd";
import { defineComponent, h } from "vue";

import { getTagProps, validateTagProps } from "./utils";

smoothDnD.dropHandler = dropHandlers.reactDropHandler().handler;
smoothDnD.wrapChild = false;

type EventKey ="drag-start"|"drag-end"|"drag-enter"|"drag-leave"|"drop"|"drop-ready"

const EventEmitterMap:Record<EventKey,string>={
  "drag-start":"onDragStart",
  "drag-end":"onDragEnd",
  "drag-enter":"onDragEnter",
  "drag-leave":"onDragLeave",
  "drop":"onDrop",
  "drop-ready":"onDropReady"
}

export const SmoothDndContainer=defineComponent({
  name:"SmoothDndContainer",
  setup(){
    return{
      container: null as SmoothDnD|null
    }
  },
  mounted(){
    const options:any=Object.assign({},this.$props);
    for (const key in EventEmitterMap) {
      const eventKey=key as EventKey;
      options[EventEmitterMap[eventKey]]=(props:any)=>{
        this.$emit(eventKey,props);
      }
    }
    const containerElement=this.$refs.container||this.$el;
    this.container=smoothDnD(containerElement,options)
  },
  unmounted(){
    if(this.container){
      try{
        this.container.dispose();
      }catch(e){
        console.log("e",e);
      }
    }
  },
  emits:['drag-start','drag-end','drag-enter','drag-leave','drop','drop-ready'],
  props:{
    orientation:{type:String,default:"vertical"},
    removeOnDropOut:{type:Boolean,default:false},
    autoScrollEnabled:{type:Boolean,default:true},
    animationDuration:{type:Number,default:250},
    behaviour:{type:String},
    groupName:{type:String},
    dragHandleSelector:{type:String},
    nonDragAreaSelector:{type:String},
    lockAxis:{type:String},
    dragClass:{type:String},
    dropClass:{type:String},
    dragBeginDelay:{type:Number},
    getChildPayload:{type:Function},
    shouldAnimateDrop:{type:Function},
    shouldAcceptDrop:{type:Function},
    getGhostParent:{type:Function},
    dropPlaceholder:{type:[Object,Boolean]},
    tag:{
      validator:validateTagProps,
      default:"div"
    }
  },
  render(){
    const tagProps=getTagProps(this);
    return h(
      tagProps.value,
      Object.assign({},{ref:"container"},tagProps.props),
      this.$slots.default?.()
    )
  }
})